package cate.game.activity.mtowerchallenge;

import cate.common.table.activity.mtower.MTowerLevelRow;
import cate.common.table.activity.mtower.MTowerMopRow;
import cate.common.table.d.GDFight;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDOperation;
import cate.common.util.GameResult;
import cate.game.activity.base.core.RoleFarmActivitySingle;
import cate.game.activity.mtowerchallenge.msg.MTowerDataResp;
import cate.game.activity.mtowerchallenge.po.MTowerLevel;
import cate.game.framework.GameException;
import cate.game.play.part.FightSide;
import cate.game.play.proce.play.PlayPO;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import cate.game.role.farm.PlayTimes;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;

import java.util.*;

public class MTowerChallengeActivity extends RoleFarmActivitySingle {
    @NoteField(value = "获得星星数")
    public int star;

    @NoteField(value = "关卡信息", detail = "map<层数id，关卡信息>")
    public Map<Integer, MTowerLevel> levelMap;

    @NoteField("已解锁的层数")
    public Set<Integer> unLockLevel;

    @NoteField("剩余扫荡次数")
    public int mopTimes;


    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (levelMap == null) {
            levelMap = new HashMap<>();
        }
        levelMap.values().forEach(MTowerLevel::initLevel);
        if (unLockLevel == null) {
            unLockLevel = new HashSet<>();
        }
    }

    @Override
    public void onRoleEnd() {
        star = 0;
        levelMap.clear();
        unLockLevel.clear();
        mopTimes = 0;
    }

    @Override
    public int getFightFuncId() {
        return GDFunc.M_TOWER;
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    public void noticeUpdate() {
        if (enable()) {
            role.sendNow(new MTowerDataResp(this));
        }
    }

    @Override
    public void excelCheck() {
        super.excelCheck();
        checkOpenLevel();
    }

    @Override
    public void onDaySpan(boolean silence) {
        super.onDaySpan(silence);
        if (enable()) {
            MTowerMopRow mopRow = role.getGame().table.mTower.mop.showMop(configTid());
            if (mopRow != null) {
                mopTimes = mopRow.mopTimes;
            }
            checkOpenLevel();
            levelMap.values().forEach(MTowerLevel::onDaySpan);
            if (!silence) {
                noticeUpdate();
            }

        }
    }

    private void checkOpenLevel() {
        unLockLevel.clear();
        int day = role.getGame().getOpenDay();
        List<Integer> levels = role.getGame().table.mTower.levelBase.showLevels(day,configTid());
        unLockLevel.addAll(levels);
    }

    public GameResult<MTowerChallengeActivity> challenge(int level) {
        GameResult<MTowerChallengeActivity> r = new GameResult<>();
        if (fighting) {
            return r.fail("当前正在战斗中");
        }
        if (!unLockLevel.contains(level)) {
            return r.fail("该关卡未解锁");
        }
        MTowerLevelRow row = showLevelRow(level);
        if (row == null) {
            return r.fail("挑战关卡不存在");
        }
        MTowerLevelRow rowBefore = showLevelRow(level - 1);
        if (rowBefore != null) {
            if (!levelMap.containsKey(rowBefore.id)) {
                return r.fail("请先挑战前置关卡");
            }
        }
        r = doChallenge(level, row);
        return r;
    }

    private MTowerLevelRow showLevelRow(int level) {
        MTowerLevelRow row = role.getGame().table.mTower.levelBase.get(level);
        return row;
    }

    private GameResult<MTowerChallengeActivity> doChallenge(int level, MTowerLevelRow row) {
        GameResult<MTowerChallengeActivity> r = new GameResult<>();
        EcResult<FightSide> fsResult = role.getGame().fight.side.createFightSideByCode(GDFight.Team.B, row.dynInsCode);
        if (!fsResult.ok()) {
            return r.fail(fsResult.message);
        }
        MTowerFTC context = new MTowerFTC(role, getFightFuncId(), row);
        context.funcId = getFightFuncId();
        context.playStory.level = level;
        EcResult<PlayPO> fightRes =  role.getGame().play.startByRole(role, context, fsResult.data);
        if (!fightRes.ok()) {
            return r.fail(fightRes.message);
        }
        this.startFighting();
        return r;
    }

    public MTowerLevel showLevel(int combatNum) {
        MTowerLevel level = levelMap.get(combatNum);
        if (level == null) {
            level = new MTowerLevel(combatNum);
            level.initLevel();
        }
        levelMap.put(combatNum, level);
        return level;
    }

    public GameResult<MTowerChallengeActivity> mop(int level) {
        GameResult<MTowerChallengeActivity> r = new GameResult<>();
        if (fighting) {
            return r.fail("当前正在战斗中");
        }
        if (!unLockLevel.contains(level)) {
            return r.fail("该关卡未解锁");
        }
        if (mopTimes <= 0) {
            return r.fail("今日无扫荡次数");
        }
        MTowerLevelRow row = showLevelRow(level);
        if (row == null) {
            return r.fail("挑战关卡不存在");
        }
        if (!levelMap.containsKey(level) || levelMap.get(level).challenge.size() < row.challengeIds.size()) {
            return r.fail("该关卡不可扫荡");
        }
        MixRes rewardRes = new MixRes(row.mopRewardStr);
        if (rewardRes.isEmpty()) {
            return r.fail("扫荡奖励未配置");
        }
        int mopNow = levelMap.get(level).mopTime + 1;
        MTowerMopRow mopRow = role.getGame().table.mTower.mop.showMop(configTid());
        if (mopRow != null) {
            if (mopNow > mopRow.mopTimes) {
                return r.fail("该关卡今日无扫荡次数");
            }

        }
        Map<Integer, String> mopCosts = row.mopCosts;
        String costStr = mopCosts.get(mopNow);
        if (costStr.isEmpty()) {
            return r.fail("扫荡配置错误");

        }
        MixRes cost = new MixRes(costStr);
        GameResult<MixResItem> consume = cost.consumeCheck(role);
        if (!consume.ok()) {
            return r.fail(consume);
        }
        cost.consume(role);
        EcResult<?> exe = new MixResAdder().setRes(rewardRes)
                .setOperation(GDOperation.M_TOWER)
                .setOperationSub(level)
                .setDialogReward(true)
                .setSendMailWhenFull(true)
                .exe(role);
        mopTimes --;
        levelMap.get(level).mopTime ++ ;
        noticeUpdate();
        return r;
    }

    public void updateLevel() {
        star = 0;
        levelMap.values().forEach(
                a -> {
                    star += a.challenge.size();
                });
    }
}
